package ru.rchervot.sanasar.client.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

import ru.rchervot.sanasar.client.model.filters.Filter;



public class DefaultQuery implements Query {
	
	private static Sort DEFAULT_SORT_ORDER = new SortName();
	private static QueryJoin DEFAULT_JOIN_OPERATOR = new QueryJoinOr();
	private HashMap<String, Integer> filtersPositions = new HashMap<String, Integer>();
	private Sort orderBy;
	
	private DefaultQuery() {} // Do not use! this constructor for serialization only
	
	public DefaultQuery(int pageSize, int userId) {
		filters = new ArrayList<Filter>();
		joinOperator = DEFAULT_JOIN_OPERATOR;
		orderBy = DEFAULT_SORT_ORDER;
		this.pageSize = pageSize;
		this.userId = userId;
	}
	
	private DefaultQuery(ArrayList<Filter> filters, Sort orderBy,
			QueryJoin joinOperator, int pageSize, int userId) {
		this(pageSize, userId);
		
		this.filters = filters;
		this.orderBy = orderBy;
		this.joinOperator = joinOperator;
	}
	
	
	public static Query build(ArrayList<Filter> filters, Sort orderBy,
			QueryJoin joinOperator, int pageSize, int userId) {
		return new DefaultQuery(filters, orderBy, joinOperator, pageSize, userId);
	}
	
	int ID;

	public int getID() {
		return ID;
	}
	
	public void setID(int id) {
		ID = id;
	}
	
	private int pageSize;
	
	public int getPageSize() {
		return pageSize;
	}
	
	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}
	
    public int getPageOffset() {
		return (offset / pageSize) * pageSize;
	}
	
	HashMap<String, QueryParameter> parameters;

	public HashMap<String, QueryParameter> getParameters() {
		return parameters;
	}

	public void setParameters(HashMap<String, QueryParameter> parameters) {
		this.parameters = parameters;
	}
	
	private ArrayList<Filter> filters;

	public Filter getFilter(int index) {
		return filters.get(index);
	}
	
	@Override
	public Filter getFilter(String filterName) {
		Integer i = filtersPositions.get(filterName);
		
		if (i != null) {
			return filters.get(i);
		} else {
			return null;
		}
		
	}
	
	public void addFilter(Filter f) {
		int i = filters.size();
		filters.add(i, f);
		filtersPositions.put(f.getName(), i);
	}
	
	public void removeFilter(int i) {
		filtersPositions.remove(filters.get(i).getName());
		filters.remove(i);
	}
	
	@Override
	public Set<String> getFiltersNames() {
		return filtersPositions.keySet();
	}

	@Override
	public void removeFilter(String filterName) {
		Integer i = filtersPositions.get(filterName);
		
		if (i != null) {
			filters.remove(i);
			filtersPositions.remove(filterName);
		}
	}
	
	public int filtersCount() {
		return filters.size();
	}
	
	private int offset;
	
	public void setOffset(int offset) {
		this.offset = offset;
	}

	public int getOffset() {
		return offset;
	}

	public void setOrderBy(Sort orderBy) {
		this.orderBy = orderBy;
	}

	public Sort getOrderBy() {
		return orderBy;
	}
	
	@Override
	public String toString() {
		StringBuffer fs = new StringBuffer();
		
		for (Filter f : filters) {
			fs.append("\n" + f.toString());
		}
		
		return "query[ID:" + ID + ", offset: " + offset + ", joinOperator: " + joinOperator + 
		", pageSize: " + pageSize + ", orderBy: " + orderBy + fs.toString() + "]"; 
	}
	
	protected QueryJoin joinOperator;
	
	public void setJoinOperator(QueryJoin jo) {
		joinOperator = jo; 
	}
	
	public QueryJoin getJoinOperator() {
		return joinOperator;
	}
	

	private Integer userId;

	@Override
	public Integer getUserId() {
		return userId;
	}

	@Override
	public boolean isSaved() {
		return ID == 0;
	}

	


}
